"""
评论服务实现
"""
from typing import List, Dict, Any, Optional, Callable
from datetime import datetime
import json
import uuid

from app.services.comment_service import ICommentService
from app.services.ai_service import IAIService
from app.services.base_service import Event
from app.models.comment import Comment
from app.utils.logger import Logger
from app.services.service_locator import ServiceLocator


class CommentService(ICommentService):
    """
    评论服务实现
    """
    
    def __init__(self):
        """
        初始化评论服务
        """
        super().__init__()
        
        # 获取日志记录器
        self.logger = Logger.get_logger("comment_service")
        
        # 评论列表，按时间排序
        self._comments: List[Comment] = []
        
        # 评论字典，用于快速查找
        self._comment_dict: Dict[str, Comment] = {}
        
        # 最大评论数量
        self._max_comments = 1000
        
        # AI 服务
        self._ai_service: Optional[IAIService] = None
        
        # 事件监听器字典，键为事件类型，值为监听器列表
        self._listeners: Dict[str, List[Callable[[Event], None]]] = {}
        
        self.logger.info("评论服务初始化完成")
    
    def add_listener(self, event_type: str, listener: Callable[[Event], None]) -> None:
        """
        添加事件监听器
        
        @param event_type: 事件类型
        @param listener: 监听器函数，接收一个 Event 参数
        """
        if event_type not in self._listeners:
            self._listeners[event_type] = []
        
        if listener not in self._listeners[event_type]:
            self._listeners[event_type].append(listener)
    
    def remove_listener(self, event_type: str, listener: Callable[[Event], None]) -> bool:
        """
        移除事件监听器
        
        @param event_type: 事件类型
        @param listener: 监听器函数
        @return: 是否成功移除
        """
        if event_type in self._listeners and listener in self._listeners[event_type]:
            self._listeners[event_type].remove(listener)
            return True
        return False
    
    def clear_listeners(self, event_type: str = None) -> None:
        """
        清除事件监听器
        
        @param event_type: 事件类型，如果为 None 则清除所有监听器
        """
        if event_type is None:
            self._listeners.clear()
        elif event_type in self._listeners:
            self._listeners[event_type].clear()
    
    def notify(self, event_type: str, data: Any = None) -> None:
        """
        通知事件
        
        @param event_type: 事件类型
        @param data: 事件数据
        """
        # 创建事件对象
        event = Event(event_type, data)
        
        # 调用监听器
        if event_type in self._listeners:
            for listener in self._listeners[event_type]:
                try:
                    listener(event)
                except Exception as e:
                    # 这里可以添加日志记录
                    self.logger.error(f"事件监听器异常: {str(e)}")
    
    def set_ai_service(self, ai_service: IAIService) -> None:
        """
        设置 AI 服务
        
        @param ai_service: AI 服务实例
        """
        self._ai_service = ai_service
        self.logger.debug("已设置 AI 服务")
    
    def set_max_comments(self, max_comments: int) -> None:
        """
        设置最大评论数量
        
        @param max_comments: 最大评论数量
        """
        if max_comments > 0:
            self._max_comments = max_comments
            self.logger.debug(f"已设置最大评论数量: {max_comments}")
            
            # 如果当前评论数量超过最大值，则删除旧的评论
            self._trim_comments()
    
    def add_comment(self, comment_data: Dict[str, Any], matched_keyword: bool = False) -> Comment:
        """
        添加评论
        
        @param comment_data: 评论数据
        @param matched_keyword: 是否已匹配关键词
        @return: 评论对象
        """
        # 增加详细日志，记录原始字段
        self.logger.debug(f"添加评论 - 原始数据: platform={comment_data.get('platform')}, "
                         f"nickname={comment_data.get('nickname')}, "
                         f"user_name={comment_data.get('user_name')}, "
                         f"username={comment_data.get('username')}")
        
        self.logger.info(f"开始添加评论: ID={comment_data.get('id', '未知')}")
        
        # 创建评论对象 - 增强用户名字段获取逻辑
        comment = Comment(
            id=comment_data.get("id", str(uuid.uuid4())),
            user_id=comment_data.get("user_id", ""),
            user_name=comment_data.get("user_name", 
                                     comment_data.get("username", 
                                                   comment_data.get("nickname", "未知用户"))),
            content=comment_data.get("content", ""),
            timestamp=comment_data.get("timestamp", datetime.now().isoformat()),
            platform=comment_data.get("platform", ""),
            metadata=comment_data.get("metadata", {})
        )
        self.logger.debug(f"创建评论对象: ID={comment.id}, 用户={comment.user_name}")
        
        # 添加关键词匹配标记
        comment.matched_keyword = matched_keyword
        if matched_keyword:
            self.logger.info(f"评论已标记为匹配关键词: ID={comment.id}")
        
        # 添加到评论列表和字典
        self._comments.append(comment)
        self._comment_dict[comment.id] = comment
        self.logger.debug(f"评论已添加到列表和字典，当前评论数: {len(self._comments)}")
        
        # 如果评论数量超过最大值，则删除旧的评论
        if len(self._comments) > self._max_comments:
            self.logger.info(f"评论数量({len(self._comments)})超过最大值({self._max_comments})，将裁剪旧评论")
        self._trim_comments()
        
        # 记录日志
        self.logger.debug(f"添加评论: {comment.user_name} - {comment.content}")
        
        # 触发评论添加事件
        self.logger.info(f"触发评论添加事件: comment_added, ID={comment.id}")
        self.notify("comment_added", comment)
        
        # 处理评论
        self.logger.info(f"开始处理评论: ID={comment.id}")
        self._process_comment(comment)
        
        self.logger.info(f"评论添加和处理完成: ID={comment.id}")
        return comment
    
    def get_comment(self, comment_id: str) -> Optional[Comment]:
        """
        获取评论
        
        @param comment_id: 评论 ID
        @return: 评论对象，如果不存在则返回 None
        """
        return self._comment_dict.get(comment_id)
    
    def get_comments(self) -> List[Comment]:
        """
        获取所有评论
        
        @return: 评论列表
        """
        return self._comments.copy()
    
    def get_recent_comments(self, count: int = 50) -> List[Comment]:
        """
        获取最近的评论
        
        @param count: 评论数量
        @return: 评论列表
        """
        return self._comments[-count:] if count < len(self._comments) else self._comments.copy()
    
    def clear_comments(self) -> None:
        """
        清空评论
        """
        self._comments.clear()
        self._comment_dict.clear()
        self.logger.debug("已清空评论")
        
        # 触发评论清空事件
        self.notify("comments_cleared", None)
    
    def save_comments(self, file_path: str) -> bool:
        """
        保存评论到文件
        
        @param file_path: 文件路径
        @return: 是否成功保存
        """
        try:
            # 将评论列表转换为字典列表
            comments_data = [comment.to_dict() for comment in self._comments]
            
            # 写入文件
            with open(file_path, "w", encoding="utf-8") as f:
                json.dump(comments_data, f, ensure_ascii=False, indent=2)
            
            self.logger.info(f"已保存评论到文件: {file_path}")
            return True
        except Exception as e:
            self.logger.error(f"保存评论到文件失败: {str(e)}")
            return False
    
    def load_comments(self, file_path: str) -> bool:
        """
        从文件加载评论
        
        @param file_path: 文件路径
        @return: 是否成功加载
        """
        try:
            # 读取文件
            with open(file_path, "r", encoding="utf-8") as f:
                comments_data = json.load(f)
            
            # 清空当前评论
            self._comments.clear()
            self._comment_dict.clear()
            
            # 添加评论
            for comment_data in comments_data:
                comment = Comment(
                    id=comment_data.get("id", str(uuid.uuid4())),
                    user_id=comment_data.get("user_id", ""),
                    user_name=comment_data.get("user_name", ""),
                    content=comment_data.get("content", ""),
                    timestamp=comment_data.get("timestamp", datetime.now().isoformat()),
                    platform=comment_data.get("platform", ""),
                    metadata=comment_data.get("metadata", {})
                )
                
                self._comments.append(comment)
                self._comment_dict[comment.id] = comment
            
            # 如果评论数量超过最大值，则删除旧的评论
            self._trim_comments()
            
            self.logger.info(f"已从文件加载评论: {file_path}")
            
            # 触发评论加载事件
            self.notify("comments_loaded", self._comments)
            
            return True
        except Exception as e:
            self.logger.error(f"从文件加载评论失败: {str(e)}")
            return False
    
    def shutdown(self) -> None:
        """
        关闭服务
        """
        self.logger.info("评论服务正在关闭...")
        
        # 清空评论
        self._comments.clear()
        self._comment_dict.clear()
        
        # 清空监听器
        self.clear_listeners()
        
        self.logger.info("评论服务已关闭")
    
    def _trim_comments(self) -> None:
        """
        裁剪评论列表，保持评论数量不超过最大值
        """
        if len(self._comments) > self._max_comments:
            # 计算需要删除的评论数量
            remove_count = len(self._comments) - self._max_comments
            
            # 获取要删除的评论
            comments_to_remove = self._comments[:remove_count]
            
            # 从字典中删除评论
            for comment in comments_to_remove:
                del self._comment_dict[comment.id]
            
            # 更新评论列表
            self._comments = self._comments[remove_count:]
            
            self.logger.debug(f"已删除 {remove_count} 条旧评论")
    
    def _process_comment(self, comment: Comment) -> None:
        """
        处理评论
        
        @param comment: 评论对象
        """
        self.logger.info(f"开始处理评论: ID={comment.id}, 用户={comment.user_name}, 内容={comment.content}")
        
        # 检查评论是否已经匹配了关键词
        if hasattr(comment, 'matched_keyword') and comment.matched_keyword:
            self.logger.info(f"评论已标记为匹配关键词，跳过AI分析: ID={comment.id}")
            # 仍然触发评论处理事件，但不进行AI分析
            self.notify("comment_processed", comment)
            return
        
        # 如果设置了 AI 服务，则分析评论
        if self._ai_service:
            self.logger.info(f"AI服务已设置，准备分析评论: ID={comment.id}")
            # 异步分析评论
            self._ai_service.analyze_comment_async(comment)
        else:
            self.logger.warning(f"AI服务未设置，无法分析评论: ID={comment.id}")
        
        # 触发评论处理事件
        self.logger.info(f"触发评论处理事件: comment_processed, ID={comment.id}")
        self.notify("comment_processed", comment)
    
    def process_message(self, message: Dict[str, Any]) -> None:
        """
        处理从 WebSocket 接收到的消息
        
        @param message: 接收到的消息
        """
        try:
            self.logger.info(f"开始处理WebSocket消息: {message}")
            
            # 检查消息是否已处理过（使用消息内容和时间戳作为唯一标识）
            message_id = message.get('id', None)
            if not message_id:
                # 如果消息没有ID，使用内容和时间戳生成一个唯一标识
                content = message.get('content', '')
                timestamp = message.get('timestamp', '')
                username = message.get('username', message.get('user_name', message.get('nickname', '')))
                message_id = f"{username}:{content}:{timestamp}"
            
            # 检查是否已处理过此消息
            if hasattr(self, '_processed_message_ids') and message_id in self._processed_message_ids:
                self.logger.warning(f"消息已处理过，跳过: {message_id}")
                return
            
            # 记录已处理的消息ID
            if not hasattr(self, '_processed_message_ids'):
                self._processed_message_ids = set()
            self._processed_message_ids.add(message_id)
            
            # 限制已处理消息集合大小，避免内存泄漏
            if len(self._processed_message_ids) > 1000:
                # 只保留最近的500条消息ID
                self._processed_message_ids = set(list(self._processed_message_ids)[-500:])
            
            # 根据消息类型处理
            if 'type' in message:
                msg_type = message['type']
                # self.logger.info(f"消息中包含类型字段: type={msg_type}")
            else:
                self.logger.info("消息中不包含类型字段，尝试推断消息类型")
                # 尝试推断消息类型
                if 'content' in message and ('username' in message or 'user_name' in message or 'nickname' in message):
                    msg_type = 'comment'
                    self.logger.info("推断为评论消息")
                elif ('username' in message or 'user_name' in message or 'nickname' in message) and ('join_type' in message or 'join_time' in message):
                    msg_type = 'join'
                    self.logger.info("推断为加入消息")
                elif ('username' in message or 'user_name' in message or 'nickname' in message) and ('gift_name' in message or 'gift_id' in message or ('content' in message and '送出' in message.get('content', ''))):
                    msg_type = 'gift'
                    self.logger.info("推断为礼物消息")
                else:
                    msg_type = 'unknown'
                    self.logger.warning("无法推断消息类型，标记为未知类型")
            
            # 获取用户名 - 增加对nickname字段的支持
            username = message.get('username', message.get('user_name', message.get('nickname', '未知用户')))
            # self.logger.info(f"提取用户名: {username}")
            
            # 根据消息类型处理
            if msg_type == 'comment':
                content = message.get('content', '')
                self.logger.info(f"处理评论消息: 用户={username}, 内容={content}")
                
                # 准备评论数据
                comment_id = message.get('id', str(uuid.uuid4()))
                self.logger.info(f"生成评论ID: {comment_id}")
                
                comment_data = {
                    "id": comment_id,
                    "user_id": message.get('user_id', ''),
                    "user_name": username,
                    "content": content,
                    "timestamp": message.get('timestamp', datetime.now().isoformat()),
                    "platform": message.get('platform', '未知平台'),
                    "metadata": message  # 保存原始消息
                }
                self.logger.debug(f"准备评论数据: {comment_data}")
                
                # 先检查是否匹配关键词
                matched_keyword = self._check_keyword_match(content)
                if matched_keyword:
                    self.logger.info(f"评论匹配了关键词，将标记为已处理: {content}")
                
                # 添加评论，传递关键词匹配标记
                self.logger.info(f"调用add_comment添加评论: ID={comment_id}, 关键词匹配={matched_keyword}")
                comment = self.add_comment(comment_data, matched_keyword)
                
                self.logger.info(f"评论添加成功: ID={comment.id}, 用户={username}, 内容={content}, 关键词匹配={matched_keyword}")
            
            # 处理礼物类型消息
            elif msg_type == 'gift':
                content = message.get('content', '')
                self.logger.info(f"处理礼物消息: 用户={username}, 内容={content}")
                
                # 准备礼物评论数据
                gift_id = message.get('id', str(uuid.uuid4()))
                self.logger.info(f"生成礼物ID: {gift_id}")
                
                # 创建礼物评论数据
                gift_data = {
                    "id": gift_id,
                    "user_id": message.get('user_id', ''),
                    "user_name": username,
                    "content": content,
                    "timestamp": message.get('timestamp', datetime.now().isoformat()),
                    "platform": message.get('platform', '未知平台'),
                    "metadata": message  # 保存原始消息
                }
                self.logger.debug(f"准备礼物评论数据: {gift_data}")
                
                # 对礼物消息直接进行AI回复，不进行关键词匹配检查
                self.logger.info(f"调用add_comment添加礼物评论: ID={gift_id}, 关键词匹配=False")
                gift_comment = self.add_comment(gift_data, False)
                
                self.logger.info(f"礼物评论添加成功: ID={gift_comment.id}, 用户={username}, 内容={content}")
            
            # 处理用户进入类型消息
            elif msg_type == 'join' or msg_type == 'enter':
                self.logger.info(f"处理用户进入消息: 用户={username}")
                
                # 通知用户进入事件
                join_event_data = {
                    "user_name": username,
                    "timestamp": message.get('timestamp', datetime.now().isoformat()),
                    "platform": message.get('platform', '未知平台'),
                    "metadata": message  # 保存原始消息
                }
                
                # 记录更详细的日志
                self.logger.info(f"正在发送用户进入事件通知，详情: {join_event_data}")
                
                self.notify("user_joined", join_event_data)
                
                # 获取流量监控服务
                from app.services.flow_monitor_service import IFlowMonitorService
                flow_monitor_service = ServiceLocator.get(IFlowMonitorService)
                
                # 记录是否获取到流量监控服务及其状态
                if flow_monitor_service:
                    self.logger.debug(f"已获取流量监控服务实例: {flow_monitor_service}")
                    
                    # 检查服务状态
                    is_monitoring = getattr(flow_monitor_service, 'is_monitoring', False)
                    self.logger.info(f"流量监控服务状态: {'正在监控' if is_monitoring else '未监控'}")
                    
                    # 检查服务配置
                    if hasattr(flow_monitor_service, 'config_service'):
                        enabled = flow_monitor_service.config_service.get("flow_welcome.enabled", False)
                        period = flow_monitor_service.config_service.get("flow_welcome.period", 30)
                        low_threshold = flow_monitor_service.config_service.get("flow_welcome.low_threshold", 10)
                        high_threshold = flow_monitor_service.config_service.get("flow_welcome.high_threshold", 50)
                        self.logger.info(f"流量监控服务配置: 启用={enabled}, 周期={period}秒, 低流量阈值={low_threshold}, 高流量阈值={high_threshold}")
                    
                    # 添加用户到流量监控服务
                    flow_monitor_service.add_user(username)
                    self.logger.info(f"已添加用户到流量监控服务: {username}")
                    
                    # 获取当前流量等级
                    current_level = flow_monitor_service.get_current_flow_level()
                    user_count = flow_monitor_service.get_last_period_count()
                    self.logger.info(f"当前流量等级: {current_level}, 用户数: {user_count}")
                    
                    # 检查待处理用户队列
                    if hasattr(flow_monitor_service, 'pending_users'):
                        pending_count = len(flow_monitor_service.pending_users)
                        self.logger.info(f"待处理用户队列长度: {pending_count}, 当前用户: {username}在队列中")
                else:
                    self.logger.warning("流量监控服务不存在，无法处理用户进入事件")
            
            # 其他类型的消息可以在这里处理
            # elif msg_type != 'unknown':
            #     self.logger.info(f"收到非评论类型消息: type={msg_type}, 用户={username}")
            # else:
            #     self.logger.warning(f"跳过未知类型消息处理")
            
        except Exception as e:
            self.logger.error(f"处理消息失败: {str(e)}")
            import traceback
            self.logger.error(traceback.format_exc())
    
    def _check_keyword_match(self, content: str) -> bool:
        """
        检查内容是否匹配关键词
        
        @param content: 评论内容
        @return: 是否匹配
        """
        try:
            # 获取配置服务
            from app.services.config_service import IConfigService
            from app.services.audio_service import IAudioService
            
            config_service = ServiceLocator.get(IConfigService)
            if config_service:
                # 检查关键词功能是否启用
                keyword_enabled = config_service.get("keyword.enabled", False)
                if not keyword_enabled:
                    return False
                
                # 获取音频服务
                audio_service = ServiceLocator.get(IAudioService)
                if not audio_service:
                    return False
                
                # 检查是否有关键词话术管理器
                if not hasattr(audio_service, 'keyword_speech_manager') or not audio_service.keyword_speech_manager:
                    return False
                
                # 查找匹配的关键词
                keyword, file_name = audio_service.keyword_speech_manager.find_matching_keyword(content)
                return bool(keyword and file_name)
        except Exception as e:
            self.logger.error(f"检查关键词匹配失败: {str(e)}")
        
        return False 